<?php
namespace app\service;

use support\Request;
use support\Response;
use BusinessException;
use app\model\UploadFileModel;

class UploadService
{
    /**
     * 允许上传的文件类型
     * @var array
     */
    protected $allowedTypes = [
        'image' => ['jpg', 'jpeg', 'png', 'gif'],
        'document' => ['pdf', 'doc', 'docx', 'xls', 'xlsx'],
        'video' => ['mp4', 'avi', 'mov'],
        'audio' => ['mp3', 'wav']
    ];

    /**
     * 上传文件大小限制（默认10MB）
     * @var int
     */
    protected $maxSize = 10 * 1024 * 1024;

    /**
     * 上传文件保存目录
     * @var string
     */
    protected $uploadPath = 'public/uploads';

    /**
     * 文件模型
     * @var UploadFileModel
     */
    protected $model;

    public function __construct()
    {
        $this->model = new UploadFileModel();
    }

    /**
     * 上传单个文件
     * @param Request $request
     * @param string $field 文件字段名
     * @param string|null $type 文件类型限制(image|document|video|audio)
     * @param int|null $uploadBy 上传者ID
     * @return array
     * @throws BusinessException
     */
    public function uploadFile(Request $request, string $field = 'file', ?string $type = null, ?int $uploadBy = null): array
    {
        if (!$request->hasFile($field)) {
            throw new BusinessException('请选择要上传的文件');
        }

        $file = $request->file($field);
        
        // 检查文件上传是否出错
        if (!$file->isValid()) {
            throw new BusinessException('文件上传失败');
        }

        // 获取文件信息
        $originalName = $file->getUploadName();
        $extension = strtolower($file->getUploadExtension());
        $size = $file->getSize();
        $mimeType = $file->getUploadMineType();

        // 检查文件类型
        if ($type !== null) {
            if (!isset($this->allowedTypes[$type]) || !in_array($extension, $this->allowedTypes[$type])) {
                throw new BusinessException('不支持的文件类型');
            }
        }

        // 检查文件大小
        if ($size > $this->maxSize) {
            throw new BusinessException('文件大小超出限制');
        }

        // 生成唯一文件名
        $fileName = uniqid() . '.' . $extension;
        
        // 确保上传目录存在
        $uploadDir = public_path() . '/' . $this->uploadPath;
        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }

        // 移动文件到目标目录
        $file->move($uploadDir . '/' . $fileName);

        // 文件信息
        $fileInfo = [
            'original_name' => $originalName,
            'file_name' => $fileName,
            'file_path' => '/' . $this->uploadPath . '/' . $fileName,
            'file_type' => $type,
            'extension' => $extension,
            'size' => $size,
            'mime_type' => $mimeType,
            'upload_by' => $uploadBy,
            'status' => 1
        ];

        // 保存文件记录
        $fileRecord = $this->model->create($fileInfo);

        // 返回文件信息
        return array_merge($fileInfo, ['id' => $fileRecord->id]);
    }

    /**
     * 上传多个文件
     * @param Request $request
     * @param string $field 文件字段名
     * @param string|null $type 文件类型限制(image|document|video|audio)
     * @param int|null $uploadBy 上传者ID
     * @return array
     * @throws BusinessException
     */
    public function uploadFiles(Request $request, string $field = 'files', ?string $type = null, ?int $uploadBy = null): array
    {
        if (!$request->hasFile($field)) {
            throw new BusinessException('请选择要上传的文件');
        }

        $files = $request->file($field);
        $results = [];

        foreach ($files as $file) {
            $results[] = $this->uploadFile($request, $field, $type, $uploadBy);
        }

        return $results;
    }

    /**
     * 删除文件
     * @param int|string $fileId 文件ID或路径
     * @return bool
     */
    public function deleteFile($fileId): bool
    {
        // 如果是文件ID
        if (is_numeric($fileId)) {
            $file = $this->model->find($fileId);
            if (!$file) {
                return false;
            }
            $filePath = $file->file_path;
            
            // 删除数据库记录
            $file->delete();
        } else {
            $filePath = $fileId;
        }

        // 删除物理文件
        $fullPath = public_path() . $filePath;
        if (file_exists($fullPath)) {
            return unlink($fullPath);
        }
        return false;
    }

    /**
     * 获取文件信息
     * @param int $fileId
     * @return UploadFileModel|null
     */
    public function getFileInfo(int $fileId)
    {
        return $this->model->find($fileId);
    }

    /**
     * 设置允许上传的文件类型
     * @param array $types
     * @return $this
     */
    public function setAllowedTypes(array $types)
    {
        $this->allowedTypes = $types;
        return $this;
    }

    /**
     * 设置上传文件大小限制
     * @param int $size 字节数
     * @return $this
     */
    public function setMaxSize(int $size)
    {
        $this->maxSize = $size;
        return $this;
    }

    /**
     * 设置上传文件保存目录
     * @param string $path
     * @return $this
     */
    public function setUploadPath(string $path)
    {
        $this->uploadPath = trim($path, '/');
        return $this;
    }
} 